package com.example.filter;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * 安全头过滤器
 * 添加各种安全相关的HTTP头
 */
@Component
@Order(1)
public class SecurityHeadersFilter implements Filter {

    @Value("${security.csp.enabled:true}")
    private boolean cspEnabled;

    @Value("${security.csp.policy:default-src 'self'}")
    private String cspPolicy;

    @Value("${security.protection.frame-options:DENY}")
    private String frameOptions;

    @Value("${security.protection.content-type-options:nosniff}")
    private String contentTypeOptions;

    @Value("${security.protection.referrer-policy:strict-origin-when-cross-origin}")
    private String referrerPolicy;

    @Value("${security.protection.hsts.enabled:true}")
    private boolean hstsEnabled;

    @Value("${security.protection.hsts.max-age:31536000}")
    private long hstsMaxAge;

    @Value("${security.protection.hsts.include-subdomains:true}")
    private boolean hstsIncludeSubdomains;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 添加安全头
        addSecurityHeaders(httpRequest, httpResponse);

        chain.doFilter(request, response);
    }

    private void addSecurityHeaders(HttpServletRequest request, HttpServletResponse response) {
        // Content Security Policy
        if (cspEnabled) {
            String policy = buildCSPPolicy(request);
            response.setHeader("Content-Security-Policy", policy);
        }

        // X-Frame-Options
        response.setHeader("X-Frame-Options", frameOptions);

        // X-Content-Type-Options
        response.setHeader("X-Content-Type-Options", contentTypeOptions);

        // Referrer Policy
        response.setHeader("Referrer-Policy", referrerPolicy);

        // X-XSS-Protection 已弃用，现代浏览器不再需要此头
        // response.setHeader("X-XSS-Protection", "1; mode=block");

        // HSTS (仅在HTTPS下)
        if (hstsEnabled && isHttps(request)) {
            String hstsValue = "max-age=" + hstsMaxAge;
            if (hstsIncludeSubdomains) {
                hstsValue += "; includeSubDomains";
            }
            hstsValue += "; preload";
            response.setHeader("Strict-Transport-Security", hstsValue);
        }

        // Permissions Policy
        response.setHeader("Permissions-Policy", buildPermissionsPolicy());

        // Cross-Origin Policies (在开发环境中放宽限制)
        if (!isDevelopment()) {
            response.setHeader("Cross-Origin-Opener-Policy", "same-origin");
            response.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
            response.setHeader("Cross-Origin-Resource-Policy", "same-origin");
        }

        // 移除可能泄露服务器信息的头
        response.setHeader("Server", "");
        response.setHeader("X-Powered-By", "");
    }

    private String buildCSPPolicy(HttpServletRequest request) {
        StringBuilder policy = new StringBuilder();
        
        // 基础策略
        policy.append("default-src 'self'; ");
        
        // 脚本策略 - 开发环境允许unsafe-eval，生产环境更严格
        if (isDevelopment()) {
            policy.append("script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://unpkg.com; ");
        } else {
            policy.append("script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://unpkg.com; ");
        }
        
        // 样式策略
        policy.append("style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net; ");
        
        // 字体策略
        policy.append("font-src 'self' data: https://fonts.gstatic.com https://cdn.jsdelivr.net; ");
        
        // 图片策略
        policy.append("img-src 'self' data: https: blob:; ");
        
        // 连接策略
        policy.append("connect-src 'self' ws: wss: https:; ");
        
        // 媒体策略
        policy.append("media-src 'self' data: blob:; ");
        
        // 对象策略
        policy.append("object-src 'none'; ");
        
        // 基础URI策略
        policy.append("base-uri 'self'; ");
        
        // 表单策略
        policy.append("form-action 'self'; ");
        
        // 框架策略
        policy.append("frame-ancestors 'none'; ");
        
        // 升级不安全请求
        if (isHttps(request)) {
            policy.append("upgrade-insecure-requests; ");
        }

        return policy.toString().trim();
    }

    private String buildPermissionsPolicy() {
        return "camera=(), " +
               "microphone=(), " +
               "geolocation=(self), " +
               "payment=(self), " +
               "usb=(), " +
               "magnetometer=(), " +
               "gyroscope=(), " +
               "accelerometer=(), " +
               "fullscreen=(self), " +
               "picture-in-picture=()";
    }

    private boolean isHttps(HttpServletRequest request) {
        return "https".equalsIgnoreCase(request.getScheme()) ||
               "https".equalsIgnoreCase(request.getHeader("X-Forwarded-Proto"));
    }

    private boolean isDevelopment() {
        String profile = System.getProperty("spring.profiles.active", "");
        return profile.contains("dev") || profile.contains("development");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化逻辑
    }

    @Override
    public void destroy() {
        // 清理逻辑
    }
}
